package com.cos.util;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

/**
  * @author: zxc
  * @return:
  * @time:  2021/5/13 16:01
  * @description: 操作mybatis的工具类
  */
public class MybatisUtils {
    //SqlSessionFactory 相当于 数据源(数据连接池)
    private static SqlSessionFactory factory;
    //ThreadLocal 可以帮助我们在单线程下保存数据在线程
    public static final ThreadLocal<SqlSession> LOCAL = new ThreadLocal<>();

    static {
        try {
            //1 读取配置文件
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
            //2 new sqlsessionFactorybuilder
            factory = new SqlSessionFactoryBuilder().build(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
      * @author: zxc
      * @return:
      * @time:  2021/5/13 16:04
      * @description: 返回数据
      */
    public static SqlSession getSession() {
        //从线程中获取数据
        SqlSession session = LOCAL.get();
        //判断是否为空
        if (session == null) {
            session=factory.openSession();
            //把获取的链接放入线程一遍多次访问的共享
            LOCAL.set(session);
        }
        return session;
    }

    /**
      * @author: zxc
      * @return:
      * @time:  2021/5/13 16:09
      * @description: 关闭session
     * 关闭资源,并且移除保存在线程的对象数据
      */
    public static void closeSession(){
        SqlSession session=getSession();
        //关闭  放回连接池
        session.close();
        //线程移除保存已经关闭的session对象
        LOCAL.remove();
    }

    /**
      * @author: zxc
      * @return:
      * @time:  2021/5/13 16:12
      * @description: 提交
      */
    public static void commit(){
        SqlSession session = getSession();
        session.commit();
        //已经提交证明操作结束所以调用关闭资源的方法
        closeSession();
    }

    /**
      * @author: zxc
      * @return:
      * @time:  2021/5/13 16:13
      * @description: 提交回滚
      */
    public static void rollback(){
        SqlSession session = getSession();
        session.rollback();
        //已经回滚证明操作异常,调用关闭资源的方法
        closeSession();
    }

    /**
      * @author: zxc
      * @return:
      * @time:  2021/5/13 16:18
      * @description: 使用泛型编写工具方法 ,获取接口对应实现类
      */
    public static <T> T getMapper(Class<T> clazz){
        SqlSession session = getSession();
        //session.getMapper 本身就是泛型方法,所以直接传递参数,直接返回T泛型数据出去即可
        T mapper = session.getMapper(clazz);
        return mapper;
    }
}
